package com.digitaldreamers.framework.activity;

import java.io.IOException;

import org.andengine.engine.Engine;
import org.andengine.engine.FixedStepEngine;
import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.AudioOptions;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.RenderOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.WakeLockOptions;
import org.andengine.engine.options.resolutionpolicy.FillResolutionPolicy;
import org.andengine.engine.options.resolutionpolicy.IResolutionPolicy;
import org.andengine.entity.scene.Scene;
import org.andengine.ui.activity.BaseGameActivity;

import android.util.DisplayMetrics;

import com.digitaldreamers.framework.BaseResourceManager;
import com.digitaldreamers.framework.BaseConstants;
import com.digitaldreamers.framework.scene.ManagedScene;
import com.digitaldreamers.framework.scene.SceneManager;

public abstract class GameActivity extends BaseGameActivity {
	protected Camera mCamera;
	protected float mCameraWidth;
	protected float mCameraHeight;
	protected float mCameraScaleFactorX;
	protected float mCameraScaleFactorY;
	protected float mActualWindowWidthInches;
	protected float mActualWindowHeightInches;
	
	@Override
	public Engine onCreateEngine(final EngineOptions pEngineOptions) {
		return new FixedStepEngine(pEngineOptions, BaseConstants.FIXED_STEP);
	}
	
	@Override
	public EngineOptions onCreateEngineOptions() {
		IResolutionPolicy resolutionPolicy = createResolutionPolicy();
		mCamera = createCamera();
		EngineOptions engineOptions = createEngineOptions(resolutionPolicy, mCamera);
		setEngineOptions(engineOptions);
		return engineOptions;
	}
	
	@Override
	public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws IOException {
		BaseResourceManager.setup(getApplicationContext(), this, mEngine, mCameraWidth, mCameraHeight, mCameraScaleFactorX, mCameraScaleFactorY);
		createResources();
		pOnCreateResourcesCallback.onCreateResourcesFinished();
	}
	
	@Override
	public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws IOException {
		ManagedScene scene = createFirstScene();
		SceneManager.getInstance().showScene(scene);
		pOnCreateSceneCallback.onCreateSceneFinished(scene);
	}
	
	@Override
	public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws IOException {
		ManagedScene managedScene = (ManagedScene)pScene;
		populateScene(managedScene);
		pOnPopulateSceneCallback.onPopulateSceneFinished();
	}
	
	protected IResolutionPolicy createResolutionPolicy() {
		FillResolutionPolicy resolutionPolicy = new FillResolutionPolicy();
		return resolutionPolicy;
	}
	
	protected Camera createCamera() {
		calculateWidthHeight();
		Camera camera = new Camera(0, 0, mCameraWidth, mCameraHeight);
		return camera;
	}
	
	protected EngineOptions createEngineOptions(IResolutionPolicy pResolutionPolicy, Camera pCamera) {
		EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.PORTRAIT_SENSOR, pResolutionPolicy, pCamera);
		return engineOptions;
	}
	
	protected void setEngineOptions(EngineOptions pEngineOptions) {
		AudioOptions audioOptions = pEngineOptions.getAudioOptions();
		audioOptions.setNeedsSound(true);
		audioOptions.setNeedsMusic(true);
		
		RenderOptions renderOptions = pEngineOptions.getRenderOptions();
		renderOptions.setDithering(true);
		renderOptions.getConfigChooserOptions().setRequestedMultiSampling(true);
		
		pEngineOptions.setWakeLockOptions(WakeLockOptions.SCREEN_ON);
	}
	
	private void calculateWidthHeight() {
		DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
		mActualWindowWidthInches = displayMetrics.widthPixels / displayMetrics.xdpi;
		mActualWindowHeightInches = displayMetrics.heightPixels / displayMetrics.ydpi;
		mCameraWidth = Math.round(Math.max(Math.min(BaseConstants.PORTRAIT__DESIGN_WINDOW_WIDTH_PIXELS * (mActualWindowWidthInches / BaseConstants.PORTRAIT__DESIGN_WINDOW_WIDTH_INCHES), BaseConstants.PORTRAIT__MAX_WIDTH_PIXELS), BaseConstants.PORTRAIT__MIN_WIDTH_PIXELS));
		mCameraHeight = Math.round(Math.max(Math.min(BaseConstants.PORTRAIT__DESIGN_WINDOW_HEIGHT_PIXELS * (mActualWindowHeightInches / BaseConstants.PORTRAIT__DESIGN_WINDOW_HEIGHT_INCHES), BaseConstants.PORTRAIT__MAX_HEIGHT_PIXELS), BaseConstants.PORTRAIT__MIN_HEIGHT_PIXELS));
		mCameraScaleFactorX = mCameraWidth / BaseConstants.PORTRAIT__DESIGN_WINDOW_WIDTH_PIXELS;
		mCameraScaleFactorY = mCameraHeight / BaseConstants.PORTRAIT__DESIGN_WINDOW_HEIGHT_PIXELS;
	}
	
	protected abstract void createResources();
	
	protected abstract ManagedScene createFirstScene();
	
	protected abstract void populateScene(ManagedScene pScene);
}
